﻿/*------------------------------------------------
 Author:ShenDuo
 CreatedDate:2019.3.19
 UpdatedDate:
 version:0.1
 ------------------------------------------------*/

using System;
using System.Linq;

namespace TrainsTraining
{
    /// <summary>
    ///     The main processing class for trains problems
    /// </summary>
    public static class Trains
    {
        /// <summary>
        ///     Get fixed path distance
        /// </summary>
        /// <param name="inputRoutes">input routes string</param>
        /// <returns>distance</returns>
        public static int? GetFixedPathDistance(string inputRoutes)
        {
            //split input string
            char[] chars = inputRoutes.ToCharArray();
            if (chars.Length < 2) return null;

            //init distance
            int totalDistance = 0;

            for (int i = 1; i < chars.Length; i++)
            {
                //calculate the distance between each node
                Model.Node startNode = PathHelper.Nodes.FirstOrDefault(x => x.Id == chars[i - 1].ToString());
                Model.Edge edge = startNode.EdgeList.FirstOrDefault(x => x.EndNodeId == chars[i].ToString());

                if (edge == null)
                {
                    //no route
                    Console.WriteLine("NO SUCH ROUTE");
                    return null;
                }

                //sum distance
                totalDistance += edge.Weight;
            }

            //result
            return totalDistance;
        }

        /// <summary>
        ///     Get the number of trips at starting point and ending point with a maximum of N stops
        /// </summary>
        /// <param name="inputRoutes">input routes string</param>
        /// <returns>trips count</returns>
        public static int? GetMaxTripsNumber(string inputRoutes)
        {
            //split input string
            char[] chars = inputRoutes.ToCharArray();
            if (chars.Length < 3) return null;

            //get all the paths between start point and end point
            System.Collections.Generic.List<Model.Path> paths = PathHelper.GetPaths(chars[0].ToString(), chars[1].ToString());

#if DEBUG
            //output eligible paths when debug mode
            foreach (Model.Path path in paths.Where(x =>
                x.Route.Length <= Convert.ToInt32(chars[2].ToString()) + 1))
                Console.WriteLine(path.Route);
#endif

            //result
            return paths.Count(x => x.Route.Length <= Convert.ToInt32(chars[2].ToString()) + 1);
        }

        /// <summary>
        ///     Get the number of trips at starting point and ending point with exactly N stops
        /// </summary>
        /// <param name="inputRoutes">input routes string</param>
        /// <returns>trips count</returns>
        public static int? GetEqualTripsNumber(string inputRoutes)
        {
            //split input string
            char[] chars = inputRoutes.ToCharArray();
            if (chars.Length < 3) return null;

            //get all the paths between start point and end point
            System.Collections.Generic.List<Model.Path> paths = PathHelper.GetPaths(chars[0].ToString(), chars[1].ToString());

#if DEBUG
            //output eligible paths when debug mode
            foreach (Model.Path path in paths.Where(x =>
                x.Route.Length == Convert.ToInt32(chars[2].ToString()) + 1))
                Console.WriteLine(path.Route);
#endif

            //result
            return paths.Count(x => x.Route.Length == Convert.ToInt32(chars[2].ToString()) + 1);
        }

        /// <summary>
        ///     Get the length of the shortest route
        /// </summary>
        /// <param name="inputRoutes">input routes string</param>
        /// <returns>distance</returns>
        public static int? GetMinDistance(string inputRoutes)
        {
            //split input string
            char[] chars = inputRoutes.ToCharArray();
            if (chars.Length != 2) return null;

            //get all the paths between start point and end point
            System.Collections.Generic.List<Model.Path> paths = PathHelper.GetPaths(chars[0].ToString(), chars[1].ToString());

#if DEBUG
            //output eligible path when debug mode
            Console.WriteLine(paths.OrderBy(x => x.Distance).FirstOrDefault()?.Route);
#endif

            //result
            return paths.Min(x => x.Distance);
        }

        /// <summary>
        ///     Get the number of different routes from starting point to ending point with a distance of less than N
        /// </summary>
        /// <param name="inputRoutes">input routes string</param>
        /// <returns>the number of different routes</returns>
        public static int? GetLessThanDistanceTripsNumber(string inputRoutes)
        {
            //split input string
            char[] chars = inputRoutes.ToCharArray();
            if (chars.Length < 3) return null;

            //get all the paths between start point and end point
            System.Collections.Generic.List<Model.Path> paths = PathHelper.GetPaths(chars[0].ToString(), chars[1].ToString());

            //get limiting conditions
            string limit = string.Join(string.Empty, chars.Skip(2));

#if DEBUG
            //output eligible paths when debug mode
            foreach (Model.Path path in paths.Where(x => x.Distance < Convert.ToInt32(limit))) Console.WriteLine(path.Route);
#endif
            //result
            return paths.Count(x => x.Distance < Convert.ToInt32(limit));
        }
    }
}